﻿using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using System.Web.Security;

namespace SharePointHelper.DLL.SSOM
{
	public class Security
	{

		/// <summary>
		/// Adds user (FBA or Windows) to SharePoint web (adds UserInfo table record)
		/// If user already exists, then returns the existing user,
		/// otherwise returns the newly created user
		/// </summary>
		/// <param name="username"></param>
		/// <param name="web"></param>
		/// <returns></returns>
		public static SPUser AddUser(string username, SPWeb web)
		{
			SPUser user = null;
			try
			{
				// init
				if (string.IsNullOrEmpty(username)) { throw new Exception("Username passed is null"); }
				if (web == null) { web = Web.GetWeb(); }
				if (web == null) { throw new Exception("SPWeb passed is null and cannot get from SPContext"); }

				// add user, then return
				user = web.EnsureUser(username);  
			}
			catch (Exception ex)
			{
				Log.WriteError("dfbhjcvxxzdsfseres", ex, "username: " + username);
				user = null;
			}
			return user;
		}
		/// <summary>
		/// Adds user (FBA or Windows) to SharePoint web (adds UserInfo table record)
		/// If user already exists, then returns the existing user,
		/// otherwise returns the newly created user
		/// </summary>
		/// <param name="username"></param>
		/// <returns></returns>
		public static SPUser AddUser(string username)
		{
			// call original
			return AddUser(username, null);
		}

		/// <summary>
		/// Add user to group
		/// </summary>
		/// <param name="user"></param>
		/// <param name="group"></param>
		public static void AddUserToGroup(SPUser user, SPGroup group)
		{
			try
			{
				group.AddUser(user);
			}
			catch (Exception ex)
			{
				Log.WriteError("dfgihkuyrsdrwea5e", ex);
			}
		}

		/// <summary>
		/// Add SharePoint user to group
		/// </summary>
		/// <param name="username"></param>
		/// <param name="groupName"></param>
		/// <param name="web"></param>
		public static void AddUserToGroup(string username, string groupName, SPWeb web)
		{
			try
			{
				// init
				if (string.IsNullOrEmpty(username)) { throw new Exception("Username passed is null"); }
				if (string.IsNullOrEmpty(groupName)) { throw new Exception("Group name passed is null"); }
				if (web == null) { web = Web.GetWeb(); }
				if (web == null) { throw new Exception("SPWeb passed is null and cannot get from SPContext"); }


				// get user
				SPUser user = AddUser(username, web);
				if (user == null) { throw new Exception("Failed to get or add user: " + username); }

				// get group
				SPGroup group = web.Groups[groupName];
				if (group == null) { throw new Exception("Failed to get group: " + groupName); }

				// add user to group
				group.AddUser(user);
			}
			catch (Exception ex)
			{
				Log.WriteError("iu987ttrddxfzEa", ex, "username: " + username + " group: " + groupName);
			}
		}

		/// <summary>
		/// Get SharePoint Group
		/// </summary>
		/// <param name="groupName"></param>
		/// <param name="web"></param>
		/// <returns></returns>
		public static SPGroup GetGroup(string groupName, SPWeb web)
		{
			SPGroup group = null;
			try
			{
				if (string.IsNullOrEmpty(groupName)) { throw new Exception("Group name passed is null"); }
				if (web == null) { web = Web.GetWeb(); }
				if (web == null) { throw new Exception("SPWeb passed is null and cannot get from SPContext"); }


				// get group
				group = web.Groups[groupName];
				if (group == null) { throw new Exception("Failed to get group with name: " + groupName); }
			}
			catch (Exception ex)
			{
				Log.WriteError("89twesdfxfgxgfxdsfr", ex, "group name: " + groupName);
				group = null;
			}
			return group;
		}

		/// <summary>
		/// Get the Currently logged in user
		/// Returns null if user not logged in or run under a service that doesn't provide 
		/// SPContext.Current.Web.CurrentUser object
		/// </summary>
		/// <returns></returns>
		public static SPUser GetUser()
		{
			SPUser user = null;
			try
			{
				if (SPContext.Current != null && SPContext.Current.Web != null && SPContext.Current.Web.CurrentUser != null)
				{
					user = SPContext.Current.Web.CurrentUser;
				}
				// otherwise, this member was probably run under service or search which doesn't have "Current User"
 			}
			catch (Exception ex)
			{
				Log.WriteError("dryt7idsdtrsdsdrtdr6cghcf", ex);
				user = null;
			}
			return user;
		}

		/// <summary>
		/// Get user by username and passed web
		/// IMPORTANT: User must exist in the UserInfo table
		/// </summary>
		/// <param name="username"></param>
		/// <param name="web"></param>
		/// <returns></returns>
		public static SPUser GetUser(string username, bool isCreateUserIfDoesntExist, SPWeb web)
		{
			SPUser user = null;
			try
			{
				// init
				if (string.IsNullOrEmpty(username)) { throw new Exception("Username passed is null"); }
				if (web == null) { web = Web.GetWeb(); }
				if (web == null) { throw new Exception("SPContext is null, can't get SPWeb"); }


				// format username
				if (!username.Contains("|"))
				{
					if (username.Contains("@"))
					{
						username = FormatClaimsBasedUsername(username, 
							Constants.FormsBasedAuthenticationMembershipProviderName, false);
					}
					else
					{
						username = FormatClaimsBasedUsername(username, Constants.DomainName, true);
					}
				}

				// get user
				if (!isCreateUserIfDoesntExist) 
				{ 
					user = web.AllUsers[username]; 
				}
				else 
				{
 					// get user if exists, otherwise create user
					user = web.EnsureUser(username); 
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("cxfhgjvkhjcgxfhdhsdr", ex, "username: " + username);
				user = null;
			}
			return user;
		}

		/// <summary>
		/// Get sharepoint user
		/// IMPORTANT: User must exist in the UserInfo table
		/// </summary>
		/// <param name="username"></param>
		/// <returns></returns>
		public static SPUser GetUser(string username)
		{
			// call original
			return GetUser(username, false, null);
		}

		/// <summary>
		/// Get user by userId passed
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="web"></param>
		/// <returns></returns>
		public static SPUser GetUserById(int userId, SPWeb web)
		{
			try
			{
				// init
				if (web == null) { Web.GetWeb(); }
				if (web == null) { throw new Exception("Failed to get SPWeb from SPContext"); }

				return web.AllUsers.GetByID(userId);
			}
			catch (Exception ex)
			{
				Log.WriteError("65u7ttydhfgdseasrstr", ex);
				return null;
			}
		}
        
		/// <summary>
		/// Get user by userId passed
		/// OVERLOAD
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="web"></param>
		/// <returns></returns>
		public static SPUser GetUserById(int userId)
		{
			try
			{
				// init
				var web = Web.GetWeb();
				if (web == null) { throw new Exception("Failed to get SPWeb from SPContext"); }

				return web.AllUsers.GetByID(userId);
			}
			catch (Exception ex)
			{
				Log.WriteError("tr67ufyhrtsrtdydtrrsdt", ex);
				return null;
			}
		}
 

		/// <summary>
		/// Get username for the currently logged in SharePoint user
		/// </summary>
		/// <param name="isFormatUsername">If true, username will be cleaned up removing domain info, etc.</param>
		/// <returns></returns>
		public static string GetUsername(bool isFormatUsername)
		{
			string username = null;
			try
			{
				// get asp.net user identity
				if (System.Web.HttpContext.Current != null
					&& System.Web.HttpContext.Current.User != null 
					&& System.Web.HttpContext.Current.User.Identity != null)
				{
					username = System.Web.HttpContext.Current.User.Identity.Name;
				}

				// try to get SPUser
				if (string.IsNullOrEmpty(username))
				{
					SPUser user = GetUser();
					if (user != null) { username = user.LoginName; }
				}

				// clean up username
				if (!string.IsNullOrEmpty(username) && isFormatUsername)
				{
					username = FormatUsername(username);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("thi7krs6thdxdfdszrz", ex);
				username = null;
			}
			return username;
		}

		/// <summary>
		/// Get username for the currently logged in SharePoint user
		/// </summary>
		/// <returns></returns>
		public static string GetUsername()
		{
			return GetUsername(true);
		}

		public const string ClaimsBasedPrefixWindowsUser = "i:0#.w";
		public const string ClaimsBasedPrefixWindowsGroup = "c:0+.w";

		public const string ClaimsBasedPrefixFormsUser = "i:0#.f";
		public const string ClaimsBasedPrefixFormsGroup = "c:0-.f";

		/// <summary>
		/// Fomat a username in the claims based authentication format
		/// </summary>
		/// <param name="username"></param>
		/// <param name="domainOrProvider"></param>
		/// <param name="isWindowsUser"></param>
		/// <returns></returns>
		public static string FormatClaimsBasedUsername(string username, string domainOrProvider, bool isWindowsUser)
		{
			try
			{
				// init
				if (string.IsNullOrEmpty(username)) { throw new Exception("Username passed is null"); }
				if (string.IsNullOrEmpty(domainOrProvider)) { throw new Exception("Domain name or sql membership provider name passed is null"); }
				if (username.Contains(@"\")) { throw new Exception("Passed username cannot contain a backslash"); }
				if (username.Contains(@"|")) { throw new Exception("Passed username cannot contain a pipe char"); }

				if (isWindowsUser)
				{
					// remove domain and claims prefix from username if it was already added.
					username = Utilities.ReplaceCaseInsensitive(username, ClaimsBasedPrefixWindowsUser + "|", "");
					username = Utilities.ReplaceCaseInsensitive(username, domainOrProvider + "\\", "");

					// format username
					username = ClaimsBasedPrefixWindowsUser + "|" + domainOrProvider + "\\" + username;
				}
				else
				{
					// remove domain and claims prefix from username if it was already added.
					username = Utilities.ReplaceCaseInsensitive(username, ClaimsBasedPrefixFormsUser + "|", "");
					username = Utilities.ReplaceCaseInsensitive(username, domainOrProvider + "|", "");
					
					// format username
					username = ClaimsBasedPrefixFormsUser + "|" + domainOrProvider + "|" + username;
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("fdyufytdrgsddssJJ6tdsf", ex, "username: " + username);
			}
			return username;
		}

		/// <summary>
		/// Format group name in Claims Based authentication format
		/// </summary>
		/// <param name="groupName"></param>
		/// <param name="domainOrProvider"></param>
		/// <param name="isWindowsUser"></param>
		/// <returns></returns>
		public static string FormatClaimsBasedGroupName(string groupName, string domainOrProvider, bool isWindowsUser)
		{
			try
			{
				// init
				if (string.IsNullOrEmpty(groupName)) { throw new Exception("Group name passed is null"); }
				if (string.IsNullOrEmpty(domainOrProvider)) { throw new Exception("Domain name or sql membership provider name passed is null"); }
				if (groupName.Contains(@"\")) { throw new Exception("Passed group name cannot contain a backslash"); }
				if (groupName.Contains(@"|")) { throw new Exception("Passed group name cannot contain a pipe char"); }

				if (isWindowsUser)
				{
					groupName = ClaimsBasedPrefixWindowsGroup + "|" + domainOrProvider + "|" + groupName;
				}
				else
				{
					groupName = ClaimsBasedPrefixFormsGroup + "|" + domainOrProvider + "|" + groupName;
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("r5y7dtytsreatreasset5", ex, "group name: " + groupName);
			}
			return groupName;
		}

		/// <summary>
		/// Format SharePoint username, stripping out extraneous stuff like domain name, 
		/// claims based auth prefix, etc.
		/// </summary>
		/// <param name="username"></param>
		/// <returns></returns>
		public static string FormatUsername(string username)
		{
			try
			{
				if (!string.IsNullOrEmpty(username))
				{
					// remove domain
					if (username.Contains(@"\"))
					{
						string[] usernameSegemented = username.Split('\\');
						if (usernameSegemented != null && usernameSegemented.Length > 1)
						{
							username = usernameSegemented[usernameSegemented.Length - 1];
						}
						else
						{
							Log.WriteError("5e7rthjdrs", "Failed to remove domain name from username: " + username);
						}
					}

					// remove prefix
					if (username.Contains("|"))
					{
						username = username.Substring(username.LastIndexOf("|") + 1);
					}

					// remove provider
					if (username.Contains(":") && username.Length > username.IndexOf(":")) 
					{ username = username.Substring(username.IndexOf(":") + 1); }

					// final cleanup
					username = username.Trim();
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("dxfhyfhrs6ttj7idr", ex, "username: " + username);
			}
			return username;
		}

		/// <summary>
		/// Format username for SharePoint user, removing claims based prefix and pipes
		/// </summary>
		/// <param name="user"></param>
		/// <returns></returns>
		public static string FormatUsername(SPUser user)
		{
			string o = null;
			try
			{
				// init
				if (user == null) { throw new Exception("SPUser passed is null"); }


				if (!string.IsNullOrEmpty(user.LoginName) && user.LoginName.Length > 2 && user.LoginName.Contains("|s-1"))
				{
					// don't use login name, it is a Windows GUID
					o = FormatUsername(user.Name);
				}
				else
				{
					o = FormatUsername(user.LoginName);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("rg7tikhukghfdf", ex);
				o = null;
			}
			return o;
		}

		/// <summary>
		/// Get the display name for the currently logged in user
		/// </summary>
		/// <returns></returns>
		public static string DisplayName()
		{
			string displayName = null;
			try
			{
				// try to get user
				SPUser user = null;
				try { user = GetUser(); } catch { }
				if (user != null) { displayName = user.Name; }
			}
			catch (Exception ex)
			{
				Log.WriteError("rsthr64uergsdfb", ex);
				displayName = null;
			}
			return displayName;
		}



		/// <summary>
		/// Get User Info ListItem
		/// </summary>
		/// <param name="web"></param>
		/// <param name="userId"></param>
		/// <returns></returns>
		public static SPListItem GetUserInfo(SPWeb web, int userId, bool isRunWithElevatedPrivileges)
		{
			SPListItem userInfo = null;
			try
			{
				// init
				if (web == null) { throw new Exception("SPWeb passed is null"); }

				if (isRunWithElevatedPrivileges)
				{
					SPSecurity.RunWithElevatedPrivileges(delegate() 
					{ userInfo = web.SiteUserInfoList.GetItemById(userId); });
				}
				else
				{
					userInfo = web.SiteUserInfoList.GetItemById(userId);
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("86oytdfgfdsrt", ex, "userId: " + userId);
				userInfo = null;
			}
			return userInfo;
		}

		public enum FullnameFormat
		{
			Firstname_Lastname,
			Lastname_Firstname,
			Lastname,
		}

		public static string GetFullname(SPWeb web, int userId, FullnameFormat format, string genericNameIfFullnameIsNull, 
			bool isRunWithElevatedPrivileges)
		{
			string fullname = null;
			try
			{
				// get userInfo object
				SPListItem userInfo = Security.GetUserInfo(web, userId, true);

				// is active user?
				bool isActive = true;
				if (userInfo != null)
				{
					try { isActive = Convert.ToBoolean(userInfo["IsActive"]); }
					catch (Exception ex) { Log.WriteError("e6ythrsgdddrt", ex); }
				}
				if (isActive)
				{
					// fullname
					string lastname = null;
					string firstname = null;
					if (userInfo != null)
					{
						firstname = Field.GetTextValue(userInfo, "FirstName");
						lastname = Field.GetTextValue(userInfo, "LastName");
					}
					if (!string.IsNullOrEmpty(lastname) && !string.IsNullOrEmpty(firstname))
					{
						if (format == FullnameFormat.Firstname_Lastname)
						{
							fullname = firstname + " " + lastname;
						}
						else if (format == FullnameFormat.Lastname_Firstname)
						{
							fullname = lastname + ", " + firstname;
						}
						else if (format == FullnameFormat.Lastname)
						{
							fullname = lastname;
						}
						else
						{
							Log.WriteError("erttr67ifgcgdf", "Unknown fullname format");
						}
					}
					else if (!string.IsNullOrEmpty(lastname)) { fullname = lastname; }

				} // active user?

				if (string.IsNullOrEmpty(fullname)) { fullname = genericNameIfFullnameIsNull; }
			}
			catch (Exception ex)
			{
				Log.WriteError("657rtidrdrsesererers", ex, "userId: " + userId);
			}
			return fullname;
		}

		/// <summary>
		/// Get user profile image url
		/// </summary>
		/// <param name="web"></param>
		/// <param name="userId"></param>
		/// <returns></returns>
		public static string GetUserImageUrl(SPWeb web, int userId)
		{
			string imageUrl = "_layouts/images/person.gif";
			try
			{
				// init
				if (web == null) { throw new Exception("SPWeb passed is null"); }

				// get picture
				imageUrl = web.SiteUserInfoList.GetItemById(userId)["Picture"].ToString();

			}
			catch (Exception ex)
			{
				Log.WriteError("dryfiuoytutdrt", ex);
			}
			return imageUrl;
		}

		/// <summary>
		/// Get SharePoint Role Definition, aka Permission Level
		/// </summary>
		/// <param name="web"></param>
		/// <param name="roleDefinitionName"></param>
		/// <returns></returns>
		public static SPRoleDefinition GetRoleDefinition(SPWeb web, string roleDefinitionName)
		{
			SPRoleDefinition role = null;
			try
			{
				// init
				if (web == null) { throw new Exception("SPWeb passed is null"); }
				if (string.IsNullOrEmpty(roleDefinitionName)) { throw new Exception("Role definition name passed is null"); }

				role = web.RoleDefinitions[roleDefinitionName];
			}
			catch (Exception ex)
			{
				Log.WriteError("dtyftidtdrdr", ex, "role definition: " + roleDefinitionName);
				role = null;
			}
			return role;
		}

		/// <summary>
		/// get users in role definition based on passed role assignments collection
		/// </summary>
		/// <param name="web"></param>
		/// <param name="roleAssignments"></param>
		/// <param name="roleDefinitionName"></param>
		/// <param name="isIncludeGroups"></param>
		/// <returns></returns>
		public static List<SPUser> GetUsersInRoleAssignment(SPWeb web, SPRoleAssignmentCollection roleAssignments,
			string roleDefinitionName, bool isIncludeGroups)
		{
			List<SPUser> users = null;
			try
			{
				// init
				if (web == null) { web = Web.GetWeb(); }
				if (web == null) { throw new Exception("SPWeb passed is null and failed to get from SPContext"); }
				if (roleAssignments == null) { throw new Exception("SPRoleAssignmentCollection passed is null"); }
				if (string.IsNullOrEmpty(roleDefinitionName)) { throw new Exception("Role definition name passed is null"); }
				roleDefinitionName = roleDefinitionName.ToLower();
				users = new List<SPUser>();


				foreach (SPRoleAssignment assignment in roleAssignments)
				{
					bool isMatch = false;
					foreach (SPRoleDefinition definition in assignment.RoleDefinitionBindings)
					{
						if (definition.Name.ToLower() == roleDefinitionName)
						{
							isMatch = true;
							break;
						}
					}
					if (isMatch)
					{
						// found user in passed role defition name
						SPUser user =  web.Users.GetByID(assignment.Member.ID);
						if (user == null)
						{
							Log.WriteError("rstydrjdhfxgt", "Failed to find userId: "
								+ assignment.Member.ID + " in web: " + web.Url);
						}
						else
						{
							if (isIncludeGroups || !user.IsDomainGroup)
							{
								users.Add(user);
							}
						}
						if (user != null) { users.Add(user); }
					}
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("tydufdgfdxxgfg", ex, "role definition: " + roleDefinitionName);
				users = null;
			}
			return users;
		}



		/// <summary>
		/// Get all the SPWeb users in an SPWeb role
		/// </summary>
		/// <param name="role"></param>
		/// <param name="isIncludeGroups"></param>
		/// <param name="isSearchChildWebs"></param>
		/// <returns></returns>
		public static List<SPUser> GetUsersInRoleDefinition(SPRoleDefinition role, bool isIncludeGroups)
		{
			List<SPUser> users = null;
			string currentWeb = null;
			try
			{
				// init
				if (role == null) { throw new Exception("SPRoleDefinition passed is null"); }
				users = new List<SPUser>();


				// loop through role assignments on web, find users bound to passed role definition
				foreach (SPRoleAssignment assignment in role.ParentWeb.RoleAssignments)
				{
					foreach (SPRoleDefinition _role in assignment.RoleDefinitionBindings)
					{
						if (_role == role)
						{
							SPUser user = role.ParentWeb.Users.GetByID(assignment.Member.ID);
							if (user == null)
							{
								Log.WriteError("ty8iewt4e6ture4w34df", "Failed to find userId: "
									+ assignment.Member.ID + " in web: " + role.ParentWeb.Url);
							}
							else
							{
								if (isIncludeGroups || !user.IsDomainGroup)
								{
									users.Add(user);
								}
							}
						}
					} // foreach role binding

				} // foreach role assignment
			}
			catch (Exception ex)
			{
				Log.WriteError("drg7tuo9yi8tredrdd", ex, "current Web: " + currentWeb);
				users = null;
			}
			return users;
		}


		/// <summary>
		/// Get all users who are in a SPWeb role
		/// </summary>
		/// <param name="web"></param>
		/// <param name="roleDefinitionName"></param>
		/// <param name="isIncludeGroups"></param>
		/// <returns></returns>
		public static List<SPUser> GetUsersInRoleDefinition(SPWeb web, string roleDefinitionName, bool isIncludeGroups)
		{
			// get SPRole
			SPRoleDefinition role = GetRoleDefinition(web, roleDefinitionName);

			// call original
			return GetUsersInRoleDefinition(role, isIncludeGroups);
		}


		/// <summary>
		/// Get all users who have permission to passed web
		/// Runs with elevated privileges
		/// </summary>
		/// <param name="web"></param>
		/// <param name="isIncludeGroups"></param>
		/// <returns></returns>
		public static List<SPUser> GetUsersInWeb(SPWeb web, bool isIncludeGroups)
		{
			List<SPUser> users = null;
			try
			{
				// init
				if (web == null) { throw new Exception("SPWeb passed is null"); }
				users = new List<SPUser>();


				foreach (SPUser user in web.Users)
				{
					if (isIncludeGroups || !user.IsDomainGroup)
					{
						// add user
						users.Add(user);
					}
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("dryrigufyggfxcd", ex);
				users = null;
			}
			return users;
		}

		public class FormsBasedAuthentication
		{
			public static MembershipProvider GetMembershipProvider(string membershipProviderName)
			{
				MembershipProvider provider = null;
				try
				{
					// init
					if (string.IsNullOrEmpty(membershipProviderName)) { membershipProviderName = 
						Constants.FormsBasedAuthenticationMembershipProviderName; }

					// get provider from web.config
					provider = Membership.Providers[membershipProviderName];
					if (provider == null) { throw new Exception("Failed to get membership provider: " + membershipProviderName); }
				}
				catch (Exception ex)
				{
					provider = null;
				}
				return provider;
			}

			public static MembershipProvider GetMembershipProvider()
			{
				// call original
				return GetMembershipProvider(string.Empty);
			}

			/// <summary>
			/// Get asp.net forms basds authentication user
			/// </summary>
			/// <param name="username"></param>
			/// <param name="provider">Membership provider</param>
			/// <returns></returns>
			public static MembershipUser GetUser(string username, MembershipProvider provider)
			{
				MembershipUser user = null;
				try
				{
					// init
					if (string.IsNullOrEmpty(username)) { throw new Exception("Username passed is null"); }
					if (!username.Contains("@")) { throw new Exception("Username invalid: " + username); }
					if (username.Contains("|")) { username = FormatUsername(username); }


					// get sql membership provider
					if (provider == null) { provider = GetMembershipProvider(); }
					if (provider == null) { throw new Exception("Failed to get FBA membership provider"); }
                    
					// get asp.net user
					user = provider.GetUser(username, false);

				}
				catch (Exception ex)
				{
					user = null;
				}
				return user;
			}

			/// <summary>
			/// Get aspnet FBA user, uses provider defined in SPHeler constants
			/// </summary>
			/// <param name="username"></param>
			/// <returns></returns>
			public static MembershipUser GetUser(string username)
			{
				return GetUser(username, null);
			}
		}

		/// <summary>
		/// get emails for passed collection of SPUsers
		/// </summary>
		/// <param name="users"></param>
		/// <returns></returns>
		public static List<string> GetEmails(ICollection<SPUser> users)
		{
			List<string> emails = null;
			try
			{
				// init
				if (users == null) { throw new Exception("No SPUsers passed"); }
				emails = new List<string>();


				foreach (SPUser user in users)
				{
					if (!string.IsNullOrEmpty(user.Email)) { emails.Add(user.Email); }
				}
			}
			catch (Exception ex)
			{
				Log.WriteError("6u5ri7ktjrhsegdzsgdsser5tg", ex);
				emails = null;
			}
			return emails;
		}

		/// <summary>
		/// Impersonate a different user
		/// Returns an SPSite object that you must dispose!
		/// You can use this with using (Impersonate()) { }
		/// </summary>
		/// <param name="siteUrl"></param>
		/// <param name="userTokenToImpersonate"></param>
		/// <returns></returns>
		public static SPSite Impersonate(string siteUrl, SPUserToken userTokenToImpersonate)
		{
			SPSite site = null;
			try
			{
				// init
				if (string.IsNullOrEmpty(siteUrl)) { throw new Exception("Site url passed is null"); }
				if (userTokenToImpersonate == null) { throw new Exception("SPUserToken passed is null"); }
			
				// get site under the passed user's context
				site = new SPSite(siteUrl, userTokenToImpersonate);
			}
			catch (Exception ex)
			{
				Log.WriteError("567657ytdfdfsdgesrewrewr", ex);
				site = null;
			}
			return site;
		}

		/// <summary>
		/// Impersonate a different user
		/// Returns an SPSite object that you must dispose!
		/// You can use this with using (Impersonate()) { }
		/// </summary>
		/// <param name="siteUrl"></param>
		/// <param name="userToImpersonate"></param>
		/// <returns></returns>
		public static SPSite Impersonate(string siteUrl, SPUser userToImpersonate)
		{
			if (userToImpersonate == null) 
			{ 
				Log.WriteError("wert4eyertdfsdsdgtf", "SPUser passed is null");
				return null;
			}
			else
			{
				// get site url
				if (string.IsNullOrEmpty(siteUrl)) { siteUrl = userToImpersonate.ParentWeb.Site.Url; }

				// call original
				return Impersonate(siteUrl, userToImpersonate);
			}
		}

		/// <summary>
		/// Impersonate a different user
		/// Returns an SPSite object that you must dispose!
		/// You can use this with using (Impersonate()) { }
		/// </summary>
		/// <param name="userToImpersonate"></param>
		/// <returns></returns>
		public static SPSite Impersonate(SPUser userToImpersonate)
		{
			return Impersonate(null, userToImpersonate);
		}

        /// <summary>
        /// Check the user's permission for SPList, SPListItem, or SPWeb
        /// </summary>
        /// <param name="user">user</param>
        /// <param name="securableObject">SPList, SPListItem, or SPWeb</param>
        /// <param name="perms">permission</param>
        /// <returns></returns>
        public static bool CheckPermissions(SPUser user, SPSecurableObject securableObject, SPBasePermissions perms)
        {
            var ret = false;

            SPWeb soWeb;
            var soListId = Guid.Empty;
            var soListItemId = 0;
            if (securableObject as SPList == null)
            {
                if (securableObject as SPListItem == null)
                {
                    if (securableObject as SPWeb == null)
                        throw new ArgumentException("securableObject must be an SPWeb, SPList or SPListItem", "securableObject");
                    soWeb = (SPWeb)securableObject;
                }
                else
                {
                    var li = (SPListItem)securableObject;
                    var pl = li.ParentList;
                    soWeb = pl.ParentWeb;
                    soListId = pl.ID;
                    soListItemId = li.ID;
                }
            }
            else
            {
                var pl = (SPList)securableObject;
                soWeb = pl.ParentWeb;
                soListId = pl.ID;
            }
            var soSite = soWeb.Site;

            using (var esite = new SPSite(soSite.ID, SPContext.Current.Site.SystemAccount.UserToken))
            using (var eweb = esite.OpenWeb(soWeb.ID))
            {
                if (securableObject is SPListItem)
                {
                    var l = eweb.Lists[soListId];
                    var li = l.GetItemById(soListItemId);
                    ret = li.DoesUserHavePermissions(user, perms);
                }
                else if (securableObject is SPList)
                {
                    var l = eweb.Lists[soListId];
                    ret = l.DoesUserHavePermissions(user, perms);
                }
                else if (securableObject is SPWeb)
                {
                    ret = eweb.DoesUserHavePermissions(user.LoginName, perms);
                }
            }
            return ret;
        }

	} // security
}
